package com.gill.demo;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;

import java.util.ArrayList;
import java.util.List;

/**
 * curator创建并设置znode权限的demo演示
 */
public class CuratorZnodeAcl {

    public CuratorFramework client;
    public static final String zkServerPath = "env:2181";

    /**
     * 实例化zk客户端
     */
    public CuratorZnodeAcl() {
        /**
         * curator连接zookeeper的策略:RetryNTimes（本次案例采用该连接策略）
         * n：重试的次数
         * sleepMsBetweenRetries：每次重试间隔的时间
         */
        RetryPolicy retryPolicy = new RetryNTimes(3, 5000);

        client = CuratorFrameworkFactory.builder()
                .authorization("digest","imooc1:123456".getBytes())//为递归创建有权限的znode进行认证
                .connectString(zkServerPath)
                .sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy)
                .namespace("workspace")
                .build();

        // 连接zk服务端
        client.start();

    }

    /**
     *
     * @Description: 关闭zk客户端连接
     */
    public void closeZKClient() {
        if (client != null) {
            this.client.close();
        }
    }

    public static void main(String[] args) throws Exception {
        // 连接zk服务端，创建zk客户端实例
        CuratorZnodeAcl curator = new CuratorZnodeAcl();
        boolean isZkCuratorStarted = curator.client.isStarted();
        System.out.println("当前客户的状态：" + (isZkCuratorStarted ? "连接中" : "已关闭"));

        // 递归创建带有权限的znode
        String nodePath = "/acl/father/child/sub";//若创建zk客户端的时候没有添加认证则只能创建第一级节点

        List<ACL> acls = new ArrayList<ACL>();
        Id imooc1 = new Id("digest", DigestAuthenticationProvider.generateDigest("imooc1:123456"));
        Id imooc2 = new Id("digest", DigestAuthenticationProvider.generateDigest("imooc2:123456"));
        acls.add(new ACL(ZooDefs.Perms.ALL, imooc1));
        acls.add(new ACL(ZooDefs.Perms.READ, imooc2));
        acls.add(new ACL(ZooDefs.Perms.DELETE | ZooDefs.Perms.CREATE, imooc2));

        // 递归创建带权限的znode（在zk服务端通过getAcl命令查看创建的znode的权限都是一样的）
		byte[] data = "spiderman".getBytes();
        curator.client.create().creatingParentsIfNeeded()
				.withMode(CreateMode.PERSISTENT)
				.withACL(acls, true)//applyToParents默认为false，即不会为新建立的父节点设置权限
				.forPath(nodePath, data);

        // 修改znode的权限
//        curator.client.setACL().withACL(acls).forPath("/curatorNode");//若是修改带有权限的znode则需要先认证

        // 关闭连接
        curator.closeZKClient();
        boolean isZkCuratorStarted2 = curator.client.isStarted();
        System.out.println("当前客户的状态：" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
    }

}
